﻿namespace HutongGames.PlayMakerEditor
{
    using HutongGames.PlayMaker;
    using System;
    using System.Collections.Generic;
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices;
    using UnityEngine;

    public static class DebugFlow
    {
        [CompilerGenerated]
        private static bool Active__BackingField;
        [CompilerGenerated]
        private static int CurrentDebugFrame__BackingField;
        [CompilerGenerated]
        private static float CurrentDebugTime__BackingField;
        [CompilerGenerated]
        private static FsmState DebugState__BackingField;
        [CompilerGenerated]
        private static FsmLog SelectedLog__BackingField;
        [CompilerGenerated]
        private static FsmLogEntry SelectedLogEntry__BackingField;
        [CompilerGenerated]
        private static int StartedDebugFrame__BackingField;
        private static FsmVariables globalVariablesCache;
        private static FsmLogEntry lastEnter;
        private static int lastEnterIndex;
        private static int selectedLogEntryIndex;
        private static readonly Dictionary<Fsm, FsmVariables> variablesCache = new Dictionary<Fsm, FsmVariables>();

        private static FsmLogEntry FindMostRecentLogEntry(int fromFrame)
        {
            if (SelectedLog == null)
            {
                return null;
            }
            FsmLogEntry entry = null;
            foreach (FsmLogEntry entry2 in SelectedLog.Entries)
            {
                if (entry2.FrameCount > fromFrame)
                {
                    return entry;
                }
                if ((entry2.LogType == FsmLogType.EnterState) || (entry2.LogType == FsmLogType.SendEvent))
                {
                    entry = entry2;
                }
            }
            return entry;
        }

        private static FsmLogEntry FindNextLogEntry(FsmLogEntry fromEntry, [Optional, DefaultParameterValue(FsmLogType.EnterState)] FsmLogType logType)
        {
            if (SelectedLog != null)
            {
                for (int i = SelectedLog.Entries.IndexOf(fromEntry) + 1; i < SelectedLog.Entries.Count; i++)
                {
                    FsmLogEntry entry = SelectedLog.Entries[i];
                    if (entry.LogType == logType)
                    {
                        return entry;
                    }
                }
            }
            return null;
        }

        private static FsmLogEntry FindPrevLogEntry(FsmLogEntry fromEntry, [Optional, DefaultParameterValue(FsmLogType.EnterState)] FsmLogType logType)
        {
            if ((SelectedLog == null) || (SelectedLog.Entries == null))
            {
                return null;
            }
            FsmLogEntry entry = null;
            foreach (FsmLogEntry entry2 in SelectedLog.Entries)
            {
                if (entry2 == fromEntry)
                {
                    return entry;
                }
                if (entry2.LogType == logType)
                {
                    entry = entry2;
                }
            }
            return entry;
        }

        public static FsmLogEntry GetLastTransition()
        {
            return FindPrevLogEntry(SelectedLogEntry, FsmLogType.Transition);
        }

        private static void RestoreNearestVariables(FsmLogEntry logEntry)
        {
            if ((logEntry.LogType == FsmLogType.EnterState) || (logEntry.LogType == FsmLogType.ExitState))
            {
                RestoreVariables(logEntry);
            }
            else if (logEntry.Event == FsmEvent.Finished)
            {
                FsmLogEntry entry = FindNextLogEntry(logEntry, FsmLogType.ExitState);
                if (entry != null)
                {
                    RestoreVariables(entry);
                }
            }
            else if (selectedLogEntryIndex == 0)
            {
                FsmLogEntry entry2 = FindNextLogEntry(logEntry, FsmLogType.EnterState);
                if (entry2 != null)
                {
                    RestoreVariables(entry2);
                }
            }
            else
            {
                FsmLogEntry entry3 = FindPrevLogEntry(logEntry, FsmLogType.EnterState);
                if (entry3 != null)
                {
                    RestoreVariables(entry3);
                }
            }
        }

        private static void RestoreVariables(FsmLogEntry logEntry)
        {
            if (logEntry == null)
            {
                Debug.Log("Bad Log Entry!");
            }
            else
            {
                if (logEntry.FsmVariablesCopy != null)
                {
                    FsmEditor.SelectedFsm.Variables.ApplyVariableValues(logEntry.FsmVariablesCopy);
                }
                else
                {
                    Debug.LogError("Missing Local Variables Cache!");
                }
                if (logEntry.GlobalVariablesCopy != null)
                {
                    FsmVariables.GlobalVariables.ApplyVariableValues(logEntry.GlobalVariablesCopy);
                }
                else
                {
                    Debug.LogError("Missing global Variables Cache!");
                }
                FsmEditor.VariableManager.UpdateView();
                GlobalVariablesWindow.UpdateView();
                FsmEditor.Repaint(false);
            }
        }

        public static void SelectLogEntry(FsmLogEntry logEntry, [Optional, DefaultParameterValue(true)] bool updateTime)
        {
            if (logEntry != null)
            {
                SelectedLogEntry = logEntry;
                DebugState = logEntry.State;
                selectedLogEntryIndex = SelectedLog.Entries.IndexOf(logEntry);
                if (updateTime)
                {
                    CurrentDebugTime = logEntry.Time;
                    CurrentDebugFrame = logEntry.FrameCount;
                }
                FsmEditor.SelectState(logEntry.State, true);
                if (logEntry.Action != null)
                {
                    FsmEditor.SelectAction(logEntry.Action, true);
                }
                FsmEditor.Repaint(true);
                if ((FsmEditorSettings.EnableDebugFlow && SelectedLog.Fsm.EnableDebugFlow) && (selectedLogEntryIndex < lastEnterIndex))
                {
                    RestoreNearestVariables(logEntry);
                }
            }
        }

        private static void SelectMostRecentLogEntry(int fromFrame)
        {
            SelectLogEntry(FindMostRecentLogEntry(fromFrame), false);
        }

        public static void SelectNextTransition()
        {
            SelectLogEntry(FindNextLogEntry(SelectedLogEntry, FsmLogType.EnterState), true);
        }

        public static void SelectPrevTransition()
        {
            SelectLogEntry(FindPrevLogEntry(SelectedLogEntry, FsmLogType.EnterState), true);
        }

        public static void Start(Fsm fsm)
        {
            UpdateTime();
            SyncFsmLog(fsm);
            Active = true;
            StartedDebugFrame = Time.frameCount;
            variablesCache.Clear();
            foreach (Fsm fsm2 in FsmEditor.FsmList)
            {
                variablesCache.Add(fsm2, new FsmVariables(fsm2.Variables));
            }
            globalVariablesCache = new FsmVariables(FsmVariables.GlobalVariables);
        }

        public static void Stop()
        {
            if (Active && Application.isPlaying)
            {
                SelectedLogEntry = null;
                Active = false;
                foreach (Fsm fsm in FsmEditor.FsmList)
                {
                    FsmVariables variables;
                    variablesCache.TryGetValue(fsm, out variables);
                    if (variables != null)
                    {
                        fsm.Variables.ApplyVariableValues(variables);
                    }
                    else
                    {
                        Debug.LogError("Missing Cached Variables!");
                    }
                }
                FsmVariables.GlobalVariables.ApplyVariableValues(globalVariablesCache);
                variablesCache.Clear();
                globalVariablesCache = null;
            }
        }

        public static void SyncFsmLog(Fsm fsm)
        {
            SelectedLog = (fsm != null) ? FsmLog.GetLog(fsm) : null;
            if (Active && (SelectedLog != null))
            {
                SelectMostRecentLogEntry(CurrentDebugFrame);
                lastEnter = SelectedLogEntry;
                lastEnterIndex = SelectedLog.Entries.IndexOf(lastEnter);
            }
        }

        public static void UpdateTime()
        {
            CurrentDebugTime = FsmTime.RealtimeSinceStartup;
            CurrentDebugFrame = Time.frameCount;
        }

        public static bool Active
        {
            [CompilerGenerated]
            get
            {
                return Active__BackingField;
            }
            [CompilerGenerated]
            private set
            {
                Active__BackingField = value;
            }
        }

        public static bool ActiveAndScrubbing
        {
            get
            {
                return (Active && (selectedLogEntryIndex < lastEnterIndex));
            }
        }

        private static int CurrentDebugFrame
        {
            [CompilerGenerated]
            get
            {
                return CurrentDebugFrame__BackingField;
            }
            [CompilerGenerated]
            set
            {
                CurrentDebugFrame__BackingField = value;
            }
        }

        public static float CurrentDebugTime
        {
            [CompilerGenerated]
            get
            {
                return CurrentDebugTime__BackingField;
            }
            [CompilerGenerated]
            private set
            {
                CurrentDebugTime__BackingField = value;
            }
        }

        public static FsmState DebugState
        {
            [CompilerGenerated]
            get
            {
                return DebugState__BackingField;
            }
            [CompilerGenerated]
            private set
            {
                DebugState__BackingField = value;
            }
        }

        public static FsmLog SelectedLog
        {
            [CompilerGenerated]
            get
            {
                return SelectedLog__BackingField;
            }
            [CompilerGenerated]
            private set
            {
                SelectedLog__BackingField = value;
            }
        }

        public static FsmLogEntry SelectedLogEntry
        {
            [CompilerGenerated]
            get
            {
                return SelectedLogEntry__BackingField;
            }
            [CompilerGenerated]
            private set
            {
                SelectedLogEntry__BackingField = value;
            }
        }

        private static int StartedDebugFrame
        {
            [CompilerGenerated]
            get
            {
                return StartedDebugFrame__BackingField;
            }
            [CompilerGenerated]
            set
            {
                StartedDebugFrame__BackingField = value;
            }
        }
    }
}

